package model.dao;

import java.io.File;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import model.bean.Dictionary;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

public class GetWordDAO {
    
    /**
     * Lấy về danh sách tất cả các từ tương ứng với nội dung phạm vi cần tìm kiếm
     * @param langSource
     * @param langTarget
     * @return
     */
    public ArrayList<Dictionary> GetListWord(String langSource, String langTarget){
        
        ArrayList<Dictionary> listWord = new ArrayList<Dictionary>();
        String xmlFilePath = "F:\\Eclipse_Project\\MathDict\\WebContent\\Dictionary\\"+langSource+""+langTarget+".xml";
        try {
            File xmlFile = new File(xmlFilePath);
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(xmlFile);
            doc.getDocumentElement().normalize();
            NodeList nList = doc.getElementsByTagName("words");
            for (int temp = 0; temp < nList.getLength(); temp++) {
                Node nNode = nList.item(temp);
                if (nNode.getNodeType() == Node.ELEMENT_NODE) {
                    Element eElement = (Element) nNode;
                    Dictionary dict = new Dictionary();
                    String word = eElement.getElementsByTagName("word").item(0).getTextContent();
                    String mean = eElement.getElementsByTagName("mean").item(0).getTextContent();
                    String img = eElement.getElementsByTagName("img").item(0).getTextContent();
                    
                    if("".equals(img)){
                        img = "not";
                    }
                    dict.setWord(word);
                    dict.setMeaning(mean);
                    dict.setImg(img);
                    listWord.add(dict);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return listWord;
    }
    
    /**
     * Lấy về danh sách tất cả các từ bắt đầu bằng chữ cái được chọn
     * @param begin
     * @param langSource
     * @param langTarget
     * @return
     */
    public ArrayList<Dictionary> GetListWordChoose(String begin, String langSource, String langTarget){
        
        ArrayList<Dictionary> listWord = new ArrayList<Dictionary>();
        String xmlFilePath = "F:\\Eclipse_Project\\MathDict\\WebContent\\Dictionary\\"+langSource+""+langTarget+".xml";
        String word = null;
        String mean = null;
        String img = "not";
    
        try {
            File xmlFile = new File(xmlFilePath);
            DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
            DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
            Document doc = dBuilder.parse(xmlFile);
            doc.getDocumentElement().normalize();
            NodeList nList = doc.getElementsByTagName("words");
            for (int temp = 0; temp < nList.getLength(); temp++) {
                Node nNode = nList.item(temp);
                if (nNode.getNodeType() == Node.ELEMENT_NODE) {
                    Element eElement = (Element) nNode;
                    Dictionary dict = new Dictionary();
                    word = eElement.getElementsByTagName("word").item(0).getTextContent();
                    if(word.startsWith(begin.toLowerCase())||word.startsWith(begin.toUpperCase())){// Kiểm tra từ có bắt đầu bằng ký tự được chọn
                        mean = eElement.getElementsByTagName("mean").item(0).getTextContent();
                        img = eElement.getElementsByTagName("img").item(0).getTextContent();
                        
                        if("".equals(img)){
                            img = "not";
                        }
                        
                        dict.setWord(word);
                        dict.setMeaning(mean);
                        dict.setImg(img);
                        listWord.add(dict);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(listWord.size()==0){
            Dictionary dict = new Dictionary();
            word = "No word begins with "+begin+""; 
            mean = "Không có từ nào bắt đầu bằng "+begin+"";
            
            dict.setWord(word);
            dict.setMeaning(mean);
            dict.setImg(img);
            
            listWord.add(dict);
        }
        return listWord;
    }
    
    /**
     * Tìm kiếm nội dung được nhập vào
     * @param itemSearch
     * @param langSource
     * @param langTarget
     * @return
     */
    public ArrayList<Dictionary> GetListWord(String itemSearch, String langSource, String langTarget) {

        Dictionary dict = new Dictionary();
        ArrayList<Dictionary> result = new ArrayList<Dictionary>();
        ArrayList<Dictionary> listWord = new ArrayList<Dictionary>();

        listWord = GetListWord(langSource, langTarget);

        int head = 0;
        int end = listWord.size() - 1;

        // Vị trí từ cần tìm trong danh sách từ điển
        int index = BinSearch(listWord, itemSearch, head, end);
        if (index != -1) {// Tìm thấy từ vừa nhập trong danh sách từ điển
            dict.setWord(listWord.get(index).getWord());
            dict.setMeaning(listWord.get(index).getMeaning());
            dict.setImg(listWord.get(index).getImg());
            result.add(dict);
        } else { // Không thấy từ vừa nhập

            /*
             * Tìm danh sách từ gần đúng
             */
            ArrayList<Integer> list1 = new ArrayList<Integer>();
            // list1 = Approximate(listWord, itemSearch);
            list1 = Search(listWord, itemSearch);

            if (list1.size() != 0) {
                for (int k = 0; k < list1.size(); k++) {
                    Dictionary dict1 = new Dictionary();

                    dict1.setWord(listWord.get(list1.get(k)).getWord());
                    dict1.setMeaning(listWord.get(list1.get(k)).getMeaning());
                    dict1.setImg(listWord.get(list1.get(k)).getImg());

                    result.add(dict1);
                }
                return result;
            }
        }
        return result;
    }

    /**
     * Tìm kiếm từ theo thuật toán tìm kiếm nhị phân
     * @param list
     * @param itemSearch
     * @param head
     * @param end
     * @return
     */
    public int BinSearch(ArrayList<Dictionary> list, String itemSearch, int head, int end) {
        int i = head;
        int j = end;
        if (i > j)
            return -1;
        int mid = (i + j) / 2;
        if (itemSearch.equals(list.get(mid).getWord())) {
            return mid;
        } else {
            if (itemSearch.compareTo(list.get(mid).getWord()) < 0) {
                j = mid - 1;
                return BinSearch(list, itemSearch, head, j);
            } else {
                i = mid + 1;
                return BinSearch(list, itemSearch, i, end);
            }
        }
    }
    
    /**
     * Tìm kiếm tuần tự
     * @param list
     * @param itemSearch
     * @return
     */
    public ArrayList<Integer> Search(ArrayList<Dictionary> list, String itemSearch){
        ArrayList<Integer> list1 = new ArrayList<Integer>();
        for(int i = 0; i< list.size(); i++){
            if(Compare(itemSearch, list.get(i).getWord())){
                list1.add(i);
            }
        }
        return list1;
    }
    
    /**
     * Tính sai số trong so sánh chuỗi
     * @param nhap
     * @return
     */
    public int ApproximatString(String str) {
        // Sai số cho phép
        int error = (int) Math.round(str.length() * 0.3);
        return error;
    }
    
    /**
     * Kiểm tra 2 chuỗi có gần giống nhau không
     * @param str1
     * @param str
     * @return
     */
    public boolean Compare(String str1, String str) {
        int error = ApproximatString(str1);
        int i = 0;
        int j = 0;
        int err = 0;
        int k = 0;
        if (str1.length() < (str.length() - error) || str1.length() > (str.length() + error))
            return false;
        while (i < str.length() && j < str1.length()) {
            if (str.toLowerCase().charAt(i) != str1.toLowerCase().charAt(j)) {
                err++;
                for (k = 1; k <= error; k++) {
                    if ((i + k < str.length()) && str.toLowerCase().charAt(i+k) == str1.toLowerCase().charAt(j)) {
                        i += k;
                        err += (k - 1);
                        break;
                    } else if ((j + k < str1.length()) && str.toLowerCase().charAt(i) == str1.toLowerCase().charAt(j+k)) {
                        j += k;
                        err += k - 1;
                        break;
                    }
                } 
            }
            i++;
            j++;
        }
        err += str.length() - i + str1.length() - j;
        if (err <= error)
            return true;
        else
            return false;
    }
    
    /**
     * Kiểm tra từ đã có trong danh sách
     * @param langSource
     * @param langTarget
     * @param word
     * @return
     */
    public boolean CheckWord(String langSource, String langTarget, String word){
    	 
    	ArrayList<Dictionary> listWord = new ArrayList<Dictionary>();
        listWord = GetListWord(langSource, langTarget);
        int head = 0;
        int end = listWord.size() - 1;
        int index = BinSearch(listWord, word, head, end);
        if(index != -1) return true;
        else return false;
    }
    
}
